using System;
using System.Runtime.CompilerServices;
using Parse.Classes;

namespace WhirliGigEdit.Classes
{
    [IgnoreNamespace]
    public class GigParse
    {
        public static string HtmlToList(string txt, string type)
        {
            switch (type)
            {
                case "ul":
                case "ol":
                    //Inform.Debug("HtmlToList Before: {0}", txt);
                    txt = ProcessXml.Process(txt, new HtmlToListMap()).output
                        .ReplaceRegex((RegularExpression)Script.Literal(@"/(\s*<br>\s*)+$/gi"), "")
                        ;
                    //Inform.Debug("HtmlToList _After: {0}", txt);
                    break;
            }
            return txt;
        }

        private static readonly RegularExpression ListToHtmlRx = (RegularExpression)Script.Literal(@"/(\t+)(.+?)(?:<br>|$)|(.*?)(<span style=""float:right"">.+?<\/span>(?:<br>|$))|(.+?)(?:<br>|$)/gi");

        public static string ListToHtml(string txt, string type)
        {
            if (type != "ol" && type != "ul") return txt;

            int idx = ListToHtmlRx.LastIndex = 0;
            int lvl = 0;
            string ot = "";
            bool atFront = true;

            // Filter extra line breaks
            string tx2;
            do
            {
                tx2 = txt;
                txt = txt.ReplaceRegex((RegularExpression)Script.Literal(@"/([\r\n ]*<br>\s*<br>[\r\n ]*)/gi"), "<br>");
            } while (tx2 != txt);

            string[] mm = ListToHtmlRx.Exec(txt);
            while (mm != null)
            {
                if (mm[1] != null)
                {
                    int l = mm[1].Length;
                    if (l > lvl)
                    {
                        ot += Times(l - lvl, "<" + type + ">") + "<li>" + mm[2].Trim();
                        atFront = false;
                    }
                    else if (l < lvl)
                    {
                        ot += "</li>" + Times(lvl - l, "</" + type + ">") + "<li>" + mm[2].Trim();
                        atFront = false;
                    }
                    else if (mm[2] != null)
                    {
                        ot += (atFront ? "" : "</li>") + "<li>" + mm[2].Trim();
                        atFront = false;
                    }
                    lvl = l;
                    //Inform.Debug("lvl={0}, mm={1}", lvl, mm[0]);
                }
                if (mm[3] != null)
                    ot += (atFront ? "" : "</li>") + "<h3>" + mm[3] + "</h3>";
                if (mm[4] != null)
                    ot += mm[4];
                if (mm[5] != null)
                    ot += (atFront ? "" : "</li>") + "<h3>" + mm[5] + "</h3>";
                idx = ListToHtmlRx.LastIndex;
                mm = ListToHtmlRx.Exec(txt);
            }
            ot += Times(lvl, "</li></" + type + ">");
            //if (idx < txt.Length)
            //    ot += txt.Substr(idx);
            ot = ot.ReplaceRegex((RegularExpression)Script.Literal(@"/(\s*<br>\s*)+$/gi"), "");
            //Inform.Debug("ListToHtml: {0}", ot);
            return ot;
        }

        private static string Times(int t, string txt)
        {
            string ot = "";
            while ((t--) > 0)
                ot += txt;
            return ot;
        }
    }


    public class HtmlToListMap : XmlMap
    {
        private int _lvl;
        private bool _consumeTabs;

        public HtmlToListMap()
        {
            _lvl = 0;
        }

        public override void Any(ParseXml po)
        {
            po.Append(MTabs(po) + po.GetFront() + po.GetOuter());
        }

        public override void Area(ParseXml po)
        {
            po.Append(MTabs(po) + po.GetFront().Trim());
        }

        public void H3(ParseXml po)
        {
            po.Append(po.GetInner().Trim());
        }

        public void Span(ParseXml po)
        {
            if (po.GetAttr("style") == "float:right")
                po.Append(" <right>" + po.GetInner().Trim());
            else
                ParseXml.ParseInner(po);
        }

        public void Ol(ParseXml po)
        {
            MLs(po);
        }

        public void Ul(ParseXml po)
        {
            MLs(po);
        }

        public void Li(ParseXml po)
        {
            _consumeTabs = true;
            ParseXml.ParseRecur(po);
        }

        private void MLs(ParseXml po)
        {
            string f = po.GetFront();
            if (f.Length > 0)
                po.Append(MTabs(po) + f);
            _lvl++;
            ParseXml.ParseRecur(po);
            _lvl--;
        }

        private string MTabs(ParseXml po)
        {
            string ot = "";
            if (_consumeTabs)
                ot = (po.Buffer().Substr(po.Buffer().Length - 4) == "<br>" ? "" : "<br>") + "\t\t\t\t\t\t\t\t\t\t".Substr(0, _lvl);
            _consumeTabs = false;
            return ot;
        }

    }
}
